package org.dawfinn.droiditarian.client.webview;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.maps.client.InfoWindow;
import com.google.gwt.maps.client.InfoWindowContent;
import com.google.gwt.maps.client.MapWidget;
import com.google.gwt.maps.client.control.LargeMapControl3D;
import com.google.gwt.maps.client.event.MarkerClickHandler;
import com.google.gwt.maps.client.geom.LatLng;
import com.google.gwt.maps.client.geom.Point;
import com.google.gwt.maps.client.geom.Size;
import com.google.gwt.maps.client.overlay.Icon;
import com.google.gwt.maps.client.overlay.Marker;
import com.google.gwt.maps.client.overlay.MarkerOptions;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.VerticalPanel;

public class WebView implements EntryPoint {

	// embed with <iframe scrolling="no"
	// src="http://droiditarian.appspot.com/WebView.html" />

	public static final String KEY_PARAM = "key";

	private static final int ICON_WIDTH = 34;
	private static final int ICON_HEIGHT = 36;
	private static final int DFL_QUERY_SIZE = 15;

	private MapWidget map = new MapWidget();
	private Label errorMsgLabel = new Label();

	private Icon deedIcon;
	private Icon pictureDeedIcon;
	private MarkerOptions deedMarkerOptions;
	private MarkerOptions pictureDeedMarkerOptions;

	private DeedLocationQueryServiceAsync querySvc = GWT
			.create(DeedLocationQueryService.class);

	private VerticalPanel mainPanel = new VerticalPanel();

	private HorizontalPanel queryParamsPanel = new HorizontalPanel();
	private Label querySizeLabel = new Label("Number of deeds: ");
	private ListBox querySizeListBox = new ListBox();

	public void onModuleLoad() {
		errorMsgLabel.setStyleName("errorMessage");
		errorMsgLabel.setVisible(false);

		map.addControl(new LargeMapControl3D());
		map.setSize("800px", "500px");
		map.setUIToDefault();
		map.clearOverlays();

		initializeQueryParamsPanel();
		mainPanel.add(queryParamsPanel);

		mainPanel.add(map);
		mainPanel.add(errorMsgLabel);
		mainPanel.setSpacing(10);
		RootPanel.get("web-view").add(mainPanel);

		initializeDeedIcons();
		displayRecentDeeds(DFL_QUERY_SIZE);
	}

	private void initializeQueryParamsPanel() {
		String[] items = { "1", "5", "10", "15", "25", "50", "100" };

		for (String item : items)
			querySizeListBox.addItem(item);

		querySizeListBox.setSelectedIndex(3);
		querySizeListBox.addChangeHandler(new ChangeHandler() {

			public void onChange(ChangeEvent event) {
				map.clearOverlays();

				String sizeString = querySizeListBox.getItemText(querySizeListBox
						.getSelectedIndex());

				displayRecentDeeds(Integer.parseInt(sizeString));
			}

		});

		queryParamsPanel.add(querySizeLabel);
		queryParamsPanel.add(querySizeListBox);
		queryParamsPanel.setSpacing(10);
	}

	private void displayRecentDeeds(final int querySize) {
		DeedLocationQueryParams params = new DeedLocationQueryParams(querySize);

		querySvc.getDeedLocations(params,
				new AsyncCallback<ClientDeedLocation[]>() {

					public void onFailure(Throwable caught) {
						errorMsgLabel.setText("error: unable to download deeds");
						errorMsgLabel.setVisible(true);
					}

					public void onSuccess(ClientDeedLocation[] result) {
						if (result.length == 0) {
							errorMsgLabel.setText("No deeds were done :(");
							errorMsgLabel.setVisible(true);
						} else {
							errorMsgLabel.setVisible(false);
						}

						for (ClientDeedLocation deed : result) {
							// not enough deeds returned to fill the buffer
							if (deed == null)
								break;

							placeDeedMarker(deed);
						}
					}

				});
	}

	private void initializeDeedIcons() {
		deedIcon = Icon.newInstance("/images/deed_marker.png");
		pictureDeedIcon = Icon.newInstance("/images/picture_deed_marker.png");

		Size iconSize = Size.newInstance(ICON_WIDTH, ICON_HEIGHT);
		Point markerAnchor = Point.newInstance(ICON_WIDTH / 2, ICON_HEIGHT / 2);
		Point windowAnchor = Point.newInstance(ICON_WIDTH, 0);

		deedIcon.setIconSize(iconSize);
		pictureDeedIcon.setIconSize(iconSize);

		deedIcon.setIconAnchor(markerAnchor);
		pictureDeedIcon.setIconAnchor(markerAnchor);

		// required to open an info window on a marker with a custom icon
		deedIcon.setInfoWindowAnchor(windowAnchor);
		pictureDeedIcon.setInfoWindowAnchor(windowAnchor);

		deedMarkerOptions = MarkerOptions.newInstance(deedIcon);
		pictureDeedMarkerOptions = MarkerOptions.newInstance(pictureDeedIcon);
	}

	private void placeDeedMarker(final ClientDeedLocation deed) {
		LatLng location = LatLng.newInstance(deed.getLatitude(), deed
				.getLongitude());

		final Marker marker = new Marker(location,
				deed.isPictureDeed() ? pictureDeedMarkerOptions : deedMarkerOptions);

		marker.addMarkerClickHandler(new MarkerClickHandler() {
			public void onClick(MarkerClickEvent event) {
				InfoWindow deedWindow = map.getInfoWindow();

				VerticalPanel cntPanel = new VerticalPanel();
				cntPanel.add(new HTML("<h3>" + deed.getDeedTitle() + "</h3>"));
				cntPanel.add(new HTML(deed.getLocalityString()));
				cntPanel.add(new HTML(deed.getCompletedDate()));

				if (deed.isPictureDeed()) {
					Image pic = new Image("/webview/deedLocationPhotoServlet?"
							+ KEY_PARAM + "=" + deed.getKey());

					// the infoWindow should know how big to be before
					// we fetch. might need to add this information to
					// ClientDeedLocation

					cntPanel.add(pic);
				}

				InfoWindowContent cnt = new InfoWindowContent(cntPanel);
				deedWindow.open(marker, cnt);
			}
		});

		map.addOverlay(marker);
	}
}
